在 Android 的程式中跨越不同 Activity 傳遞資料是非常頻繁且常見到的事情,那顯而易見的是一定也會有著非常多的方式可以達成這個目的,而其中最為常見的應該就屬使用 Intent 來傳遞。(這邊就單純以真的去傳遞資料為主,不考慮使用全域變數、SharedPreferences、Data base等儲存的方式)
其中接下來的主角 Intent 在前一篇有做過簡單的介紹,他基本的概念以及可以附加的屬性也都有做過說明,那我們今天最主要的重點也會是提過的一個屬性 額外資料。
發送
大概有了一點想法後我們也可以正式開始了,在有前一篇的了解下,我們已經可以使用 intent 來喚醒另一個 activity,那我們要是想要在這個喚起的過程中加入我們想要傳遞的資料,我們可以在創建 intent 的同時做另一件事情:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("Extra Data", "Hello!");
startActivity(intent);
在這個例子中就是我們在傳遞資料的做法,這個例子中的情境是由 FirstActivity 這個 Activity 喚醒 SecondActivity 這個 Activtiy,並且同時藉由 putExtra()
傳遞一則以 "Extra Data"
為 key value 的訊息,訊息內容是 "Hello!"
。
這邊可以稍微注意一下,在前一章有提過 putExtra()
會有兩個參數,第一個是"鍵名"(key name)、第二個是要傳遞的數據 (value),因此在這個例子中 "Extra Data"
是我們的 key ,也就是說在 SecondActivity 接收要取出數據時可以去以這個 key 做對應。
那有了發送,想當然而一定要有接收取出訊息的部分:
Intent intent = getIntent();
String data = intent.getStringExtra("Extra Data");
Log.d(*TAG*, data);
在目的地 Activity (SecondActivity) 中我們可以加入這段程式碼,其實這裡我們可以很簡單的看出他的流程,初始化好 intent 後,使用 getStringExtra()
並放入相對應的 key value 便可以取出我們目標的數據,那這裡呼應一下前面說 有各式 putExtra()
這點,因為放入的數據類型可能有許對不一樣的樣貌,所以在取出的時候想當然也會有所差異,那在這個例子中因為放入的是 String 所以我們在取出的時候所使用的也是用 getStringExtra()
。
回傳
到這邊相信使用方式應該都有了解了,那我們既然可以傳給目標,那接下來我們要做的事情當然是更進一步的讓目標這個 Activity 可以把運算完的結果回傳回來,讓原本的 Activity 可以知道對象做了甚麼事情有麼什麼結果。
那我們該如何下手才有辦法做到這個目標呢?這邊跟前面比較不太一樣的是在返回前一個 Activity 的時候,我們可以藉由點擊"返回"(或是在 Android 10 後以向右滑的手勢) 退回上一個畫面,所以我們好像沒有一個可以使用 intent 來傳遞資料的機會。
這時候我們可以稍微看一下 android dev doc 中,啟動其他 activity 的動作當我們使用 startActivity()
的時候,會是單向的。但事實上啟動其他 activity 的動作可以變成雙向的動作,那想要達到這個目的也非常的簡單,只需要我們把 startActivity()
改成 startActivityForResult()
即可,另外比較區要注意的是在 startActivityForResult()
中傳入的參數有一點點的不同,他多了一個參數 -- 請求碼。
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("Extra Data", "Hello!");
startActivityForResult(intent, 1);
看了範例程式有沒有覺得其實根本長得一模一樣阿,那多出來的這個請求碼是要用在甚麼地方呢?
其實這個請求碼是用在當返回這個 activity 的時候,我們可以使用這個請求碼(request code)來進行判斷,判斷說這一個結果是我們發出的哪一個請求回來的。這是因為當我們在開發一個大型的專案的時候,很有可能在一個 activity 中會有很多機會會去觸發其他的 activity 啟動,那這些 activity 不見得相同,因此要如何去辨別這些 activity 回傳時的不同呢?方式便是藉由這個請求碼來判斷了。
OK那發送端的第一個小部分先到這邊,我們先把接收端處理好再回來這裡。
在接收端我們也需要讓他做好準備,當他今天要返回的時候要把它打算返回的數據回傳:
Intent intent = new Intent();
intent.putExtra("data return", "Hello! I am back!");
setResult(RESULT_OK, intent);
finish();
這邊跟基本的寫法相比有一點點的區別:
setResult()
,那這個方法它是專門負責向上一個 activity 返回數據的。它裡面需要兩個參數,第一個參數是用於向上一個 activity 返回處理結果 resultCode
(通常為 RESULT_OK
、RESULT_CANCELED
這兩個值),第二個參數是我們要回傳回去的參數。finish()
結束當前這個 activity。好的,在我們完成了接收端該做的事情後,我們也該回頭把發送端處理處理,相信還記得我們剛剛是使用 startActivityForResult()
來啟動 SecondActivity 的,那在 SecondActivity 被銷毀回來的時候會去呼叫的就是我們現在要加入的部分 onActivityResult(),我們需要藉由覆寫這個方法來取得我們想要的回傳。
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnData = data.getStringExtra("data return");
Log.d(TAG, returnData);
break;
}
default:
break;
}
}
我們可以稍微先觀察一下這段程式碼,在 onActivityResult()
傳入的參數部分可以看到有三個參數,其實稍微回憶一下前面提到的東西應該不難發現他們各自有所對應。
startActivityForResult(intent, 1);
時的第二個參數,用來判斷是哪個請求出去的回傳。setResult(RESULT_OK, intent);
時的第一個參數,用來判斷回傳的結果為何。這邊了解了之後,那接下來的部分可以看出先進行判斷是由哪個 requestCode 出去的,再來回傳的結果是哪一個 resultCode,最後把回傳的數據做輸出就完成了喔。